package com.e2edour.service.impl

import java.io.{StringWriter, Writer}
import javax.xml.bind.JAXBContext

import com.e2edour.facade.req.WeiXinMsgReq
import com.e2edour.runtime.properties.AppContextConfig
import com.e2edour.runtime.utils.DigestUtil
import com.e2edour.service.WeiXinManagerService
import com.e2edour.service.actor.TuringActor
import com.e2edour.service.bo.{WeiXinNewsItem, WeiXinNewsRes, WeiXinRes, WeiXinTextRes}
import org.springframework.stereotype.Service
import javax.xml.bind.Marshaller

import com.e2edour.service.enums.WeiXinMsgType
import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler

/**
  * <p>
  *
  * @author King 
  * @since 2017/1/17
  */
@Service
class WeiXinManagerServiceImpl extends WeiXinManagerService {

  def handlerMsg(req: WeiXinMsgReq): String = {
    //发送图灵信息接口
    val turingRes = TuringActor.send(req.getContent, req.getFromUserName)

    turingRes.getCode match {
      //文本类
      case "100000" =>
        implicit val res = new WeiXinTextRes
        res.setToUserName(req.getFromUserName)
        res.setFromUserName(req.getToUserName)
        res.setMsgType(WeiXinMsgType.text.toString)
        res.setContent(turingRes.getText.replaceAll(AppContextConfig.get("old.name", "图灵机器人"), AppContextConfig.get("new.name", "小乐")))
        return parseWeixinRes

      //链接类
      case "200000" =>
        implicit val res = new WeiXinNewsRes
        res.setToUserName(req.getFromUserName)
        res.setFromUserName(req.getToUserName)
        res.setMsgType(WeiXinMsgType.news.toString)
        res.setArticleCount(1)
        val item = new WeiXinNewsItem
        val items = new java.util.ArrayList[WeiXinNewsItem]()
        items.add(item)
        item.setTitle(turingRes.getText)
        item.setUrl(turingRes.getUrl)
        res.setArticleItems(items)
        return parseWeixinRes
      //新闻
      case "302000" =>
        implicit val res = new WeiXinNewsRes
        res.setToUserName(req.getFromUserName)
        res.setFromUserName(req.getToUserName)
        var count = turingRes.getList.size
        if (count > 8) {
          //根据微信开发者文档要求 最多为8条
          count = 8
        }
        res.setArticleCount(count)
        res.setMsgType(WeiXinMsgType.news.toString)
        val items = new java.util.ArrayList[WeiXinNewsItem]()
        for (i <- 0 to count - 1) {
          val item = new WeiXinNewsItem
          val news = turingRes.getList.get(i)
          item.setTitle(news.getArticle)
          item.setUrl(news.getDetailurl)
          item.setPicUrl(news.getIcon)
          item.setDescription(news.getSource)
          items.add(item)
        }
        res.setArticleItems(items)
        return parseWeixinRes
      //菜谱
      case "308000" =>
        implicit val res = new WeiXinNewsRes
        res.setToUserName(req.getFromUserName)
        res.setFromUserName(req.getToUserName)
        var count = turingRes.getList.size
        if (count > 8) {
          //根据微信开发者文档要求 最多为8条
          count = 8
        }
        res.setArticleCount(count)
        res.setMsgType(WeiXinMsgType.news.toString)
        val items = new java.util.ArrayList[WeiXinNewsItem]()
        for (i <- 0 to count - 1) {
          val item = new WeiXinNewsItem
          val news = turingRes.getList.get(i)
          item.setTitle(news.getName)
          item.setUrl(news.getDetailurl)
          item.setPicUrl(news.getIcon)
          item.setDescription(news.getInfo)
          items.add(item)
        }
        res.setArticleItems(items)
        return parseWeixinRes
      case _ =>
        return "success"
    }
  }

  def parseWeixinRes(implicit weiXinRes: WeiXinRes): String = {
    val jaxbContext = JAXBContext.newInstance(weiXinRes.getClass)
    val marshaller = jaxbContext.createMarshaller
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    //去掉生成xml的默认报文头。
    marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
    //转换所有的适配字符，包括xml实体字符&lt;和&gt;，xml实体字符在好多处理xml
    //的框架中是处理不了的，除非序列化。
    marshaller.setProperty("com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler", new CharacterEscapeHandler {
      override def escape(chars: Array[Char], i: Int, i1: Int, b: Boolean, writer: Writer): Unit = {
        writer.write(chars, i, i1)
      }
    });
    val writer = new StringWriter
    marshaller.marshal(weiXinRes, writer)
    writer.toString
  }

  /**
    * 验证微信签名
    *
    * @param timestamp
    * @param nonce
    * @param signature
    */
  def checkSignature(timestamp: String, nonce: String, signature: String): Boolean = {
    val arr = Array(AppContextConfig.get("token", "wechatapi"), timestamp, nonce)
    val content = new StringBuffer
    for (i <- 0 to arr.length - 1) {
      content.append(arr(i))
    }
    //判断签名是否相等
    DigestUtil.SHA1(content.toString).eq(signature)
  }
}
